package cn.s1995.sloth.bizs.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.s1995.sloth.bizs.constant.CacheNames;
import cn.s1995.sloth.common.core.constant.enums.hint.Hint;
import cn.s1995.sloth.bizs.entity.Cart;
import cn.s1995.sloth.bizs.entity.Prod;
import cn.s1995.sloth.bizs.entity.Shop;
import cn.s1995.sloth.bizs.entity.Sku;
import cn.s1995.sloth.bizs.event.ShopCartEvent;
import cn.s1995.sloth.bizs.exception.BizException;
import cn.s1995.sloth.bizs.mapper.CartMapper;
import cn.s1995.sloth.bizs.oo.dto.OrderItemDTO;
import cn.s1995.sloth.bizs.oo.dto.ShopCartDTO;
import cn.s1995.sloth.bizs.oo.dto.ShopCartItemDTO;
import cn.s1995.sloth.bizs.oo.dto.ShopGetCartDTO;
import cn.s1995.sloth.bizs.oo.req.ChangeCartREQ;
import cn.s1995.sloth.bizs.service.CartService;
import cn.s1995.sloth.bizs.service.ProdService;
import cn.s1995.sloth.bizs.service.ShopService;
import cn.s1995.sloth.bizs.service.SkuService;
import cn.s1995.sloth.bizs.util.CacheManagerUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 购物车
 *
 * @author Lex
 * @date 2023-12-20 03:08:53
 */
@Service
@AllArgsConstructor
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements CartService {

    private final ApplicationContext applicationContext;
    private final ProdService prodService;
    private final SkuService skuService;
    private final ShopService shopService;
    private final CacheManagerUtil cacheManagerUtil;

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#uid")
    public void removeShopCartItemsCacheByUserId(Long uid) {

    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#userId")
    public void updateCartByShopCartParam(Long userId, Map<Long, ShopGetCartDTO> cartIdShopCartParamMap) {
        // 更新购物车满减活动id
        baseMapper.updateDiscountItemId(userId, cartIdShopCartParamMap);
    }

    @Override
    public List<ShopCartItemDTO> getShopCartItems(Long userId) {
        // 在这个类里面要调用这里的缓存信息，并没有使用aop，所以不使用注解
        List<ShopCartItemDTO> shopCartItemDtoList = cacheManagerUtil.getCache(CacheNames.shopCartItems, userId.toString());
        if (shopCartItemDtoList != null) {
            return shopCartItemDtoList;
        }

        shopCartItemDtoList = baseMapper.getShopCartItems(userId);
        // 计算产品总金额
        shopCartItemDtoList.forEach(item -> {
            item.setTotalAmount(NumberUtil.mul(item.getAmount(), item.getProdNum()));
        });
        for (ShopCartItemDTO item : shopCartItemDtoList) {
            item.setTotalAmount(NumberUtil.mul(item.getAmount(), item.getProdNum()));
        }
        cacheManagerUtil.putCache(CacheNames.shopCartItems, userId.toString(), shopCartItemDtoList);
        return shopCartItemDtoList;
    }

    @Override
    public List<ShopCartDTO> getShopCarts(List<ShopCartItemDTO> shopCartItems) {
        // 根据店铺ID划分item
        Map<Long, List<ShopCartItemDTO>> shopCartMap = shopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDTO::getShopId));

        // 返回一个店铺的所有信息
        List<ShopCartDTO> shopCartDtos = Lists.newArrayList();
        for (Long shopId : shopCartMap.keySet()) {

            // 获取店铺的所有产品项
            List<ShopCartItemDTO> shopCartItemDtoList = shopCartMap.get(shopId);

            // 构建每个店铺的购物车信息
            ShopCartDTO shopCart = new ShopCartDTO();

            // 店铺信息
            shopCart.setShopId(shopId);
            shopCart.setShopName(shopCartItemDtoList.get(0).getShopName());
            shopCart.setShopAvatar(shopCartItemDtoList.get(0).getShopAvatar());
            applicationContext.publishEvent(new ShopCartEvent(shopCart, shopCartItemDtoList));

            shopCartDtos.add(shopCart);
        }

        return shopCartDtos;
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#userId")
    public void removeShopCartItemsByCartIds(Long userId, List<Long> cartIds) {
        this.remove(
                Wrappers.lambdaQuery(Cart.class)
                        .eq(Cart::getUid, userId)
                        .in(Cart::getId, cartIds)
        );
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#userId")
    public void removeAllShopCartItems(Long userId) {
        this.remove(
                Wrappers.lambdaQuery(Cart.class)
                        .eq(Cart::getUid, userId)
        );
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#cart.uid")
    public void updateShopCartItem(Cart cart) {
        this.updateById(cart);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#userId")
    public void addShopCartItem(ChangeCartREQ req, Long userId) {
        Cart cart = new Cart();
        cart.setId(req.getCartId());
        cart.setUid(userId);
        cart.setCreateTime(LocalDateTime.now());

        BeanUtil.copyProperties(req, cart);

        // cart.setDistributionCardNo(req.getDistributionCardNo());

        this.saveOrUpdate(cart);
    }

    @Override
    public List<ShopCartItemDTO> getShopCartItemsByOrderItems(List<Long> cartIds, OrderItemDTO orderItem, Long userId) {
        if (orderItem == null && CollectionUtil.isEmpty(cartIds)) {
            return Collections.emptyList();
        }

        // 当立即购买时，没有提交的订单是没有购物车信息的
        if (CollectionUtil.isEmpty(cartIds) && Objects.nonNull(orderItem)) {
            Sku sku = skuService.getSku(orderItem.getSkuId());
            if (Objects.isNull(sku)) {
                // 订单包含无法识别的商品
                throw new BizException(Hint.APP_CONTAINS_UNRECOGNIZED_PRODUCTS);
            }
            Prod prod = prodService.getProduct(orderItem.getProdId());
            if (Objects.isNull(prod)) {
                // 订单包含无法识别的商品
                throw new BizException(Hint.APP_CONTAINS_UNRECOGNIZED_PRODUCTS);
            }

            // 拿到购物车的所有item
            ShopCartItemDTO shopCartItemDto = new ShopCartItemDTO();
            shopCartItemDto.setCartId(-1L);
            shopCartItemDto.setSkuId(orderItem.getSkuId());
            shopCartItemDto.setProdNum(orderItem.getProdCount());
            shopCartItemDto.setProdId(orderItem.getProdId());
            shopCartItemDto.setSkuName(sku.getSkuName());
            shopCartItemDto.setPic(StrUtil.isBlank(sku.getPic()) ? prod.getPic() : sku.getPic());
            shopCartItemDto.setProdName(sku.getProdName());
            shopCartItemDto.setTotalAmount(NumberUtil.mul(sku.getAmount(), orderItem.getProdCount()));
            shopCartItemDto.setAmount(sku.getAmount());
            shopCartItemDto.setDistributionCardNo(orderItem.getDistributionCardNo());
            shopCartItemDto.setCartTime(LocalDateTime.now());
            Shop shopDetail = shopService.getShop(orderItem.getShopId());
            shopCartItemDto.setShopId(shopDetail.getId());
            shopCartItemDto.setShopName(shopDetail.getName());
            shopCartItemDto.setShopAvatar(shopDetail.getAvatar());
            return Collections.singletonList(shopCartItemDto);
        }
        List<ShopCartItemDTO> dbShopCartItems = getShopCartItems(userId);

        // 返回购物车选择的商品信息
        return dbShopCartItems
                .stream()
                .filter(shopCartItemDto -> cartIds.contains(shopCartItemDto.getCartId()))
                .collect(Collectors.toList());
    }

    @Override
    public List<ShopCartItemDTO> getShopCartExpiryItems(Long userId) {
        return baseMapper.getShopCartExpiryItems(userId);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.shopCartItems, key = "#userId")
    public void cleanExpiryProdList(Long userId) {
        // // 获取失效的购物车项
        // List<ShopCartItemDTO> shopCartItems = this.getShopCartExpiryItems(userId);
        // // 删除失效的购物车项
        // this.removeByIds(shopCartItems.stream().map(ShopCartItemDTO::getCartId).collect(Collectors.toList()));

        baseMapper.cleanExpiryProdList(userId);
    }
}
